package com.zhaoqi.hr.service;

import com.aliyun.oss.OSS;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PolicyConditions;
import com.aliyun.oss.model.PutObjectRequest;
import com.zhaoqi.hr.config.OssConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 阿里云OSS文件上传服务
 */
@Service
public class OssService {

    private static final Logger log = LoggerFactory.getLogger(OssService.class);

    @Autowired
    private OSS ossClient;

    @Autowired
    private OssConfig ossConfig;

    /**
     * 上传文件到OSS
     * @param file 文件
     * @param folder 文件夹路径（如：documents/user123/）
     * @return 文件访问URL
     */
    public String uploadFile(MultipartFile file, String folder) {
        try {
            // 验证文件
            if (file.isEmpty()) {
                throw new RuntimeException("文件不能为空");
            }

            // 获取原始文件名和扩展名
            String originalFilename = file.getOriginalFilename();
            if (originalFilename == null || originalFilename.isEmpty()) {
                throw new RuntimeException("文件名不能为空");
            }

            String extension = getFileExtension(originalFilename);
            
            // 生成唯一文件名：日期/UUID.扩展名
            String dateFolder = new SimpleDateFormat("yyyy/MM/dd").format(new Date());
            String fileName = UUID.randomUUID().toString() + "." + extension;
            String objectKey = folder + "/" + dateFolder + "/" + fileName;

            // 设置文件元数据
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentLength(file.getSize());
            metadata.setContentType(file.getContentType());
            metadata.setContentDisposition("inline;filename=" + originalFilename);

            // 上传文件
            InputStream inputStream = file.getInputStream();
            PutObjectRequest putObjectRequest = new PutObjectRequest(
                    ossConfig.getBucketName(), 
                    objectKey, 
                    inputStream, 
                    metadata
            );

            ossClient.putObject(putObjectRequest);
            inputStream.close();

            // 生成文件访问URL
            String fileUrl = "https://" + ossConfig.getBucketName() + "." + ossConfig.getEndpoint() + "/" + objectKey;
            
            log.info("文件上传成功: {}", fileUrl);
            return fileUrl;

        } catch (IOException e) {
            log.error("文件上传失败", e);
            throw new RuntimeException("文件上传失败: " + e.getMessage());
        }
    }

    /**
     * 上传用户文档
     * @param file 文件
     * @param userId 用户ID
     * @return 文件访问URL
     */
    public String uploadUserDocument(MultipartFile file, Long userId) {
        return uploadFile(file, "documents/user" + userId);
    }

    /**
     * 上传用户头像
     * @param file 文件
     * @param userId 用户ID
     * @return 文件访问URL
     */
    public String uploadUserAvatar(MultipartFile file, Long userId) {
        return uploadFile(file, "avatars/user" + userId);
    }

    /**
     * 删除OSS文件
     * @param fileUrl 文件URL
     */
    public void deleteFile(String fileUrl) {
        try {
            if (fileUrl == null || fileUrl.isEmpty()) {
                return;
            }

            // 从URL中提取objectKey
            String objectKey = extractObjectKeyFromUrl(fileUrl);
            if (objectKey != null) {
                ossClient.deleteObject(ossConfig.getBucketName(), objectKey);
                log.info("文件删除成功: {}", fileUrl);
            }
        } catch (Exception e) {
            log.error("文件删除失败: " + fileUrl, e);
        }
    }

    /**
     * 从URL中提取ObjectKey
     * @param fileUrl 文件URL
     * @return ObjectKey
     */
    private String extractObjectKeyFromUrl(String fileUrl) {
        try {
            String bucketDomain = ossConfig.getBucketName() + "." + ossConfig.getEndpoint();
            if (fileUrl.contains(bucketDomain)) {
                return fileUrl.substring(fileUrl.indexOf(bucketDomain) + bucketDomain.length() + 1);
            }
        } catch (Exception e) {
            log.error("提取ObjectKey失败: " + fileUrl, e);
        }
        return null;
    }

    /**
     * 生成OSS上传签名
     * @param fileName 文件名
     * @param fileType 文件类型
     * @return 签名信息
     */
    public Map<String, String> generateUploadSignature(String fileName, String fileType) {
        try {
            // 生成唯一的文件key
            String extension = getFileExtension(fileName);
            String dateFolder = new SimpleDateFormat("yyyy/MM/dd").format(new Date());
            String key = "admin-uploads/" + dateFolder + "/" + UUID.randomUUID().toString() + "." + extension;

            // 设置上传策略
            long expireTime = 300; // 5分钟过期，给用户足够时间上传
            long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
            Date expiration = new Date(expireEndTime);

            PolicyConditions policyConds = new PolicyConditions();
            policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000); // 最大1GB
            policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, "admin-uploads/");

            String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
            byte[] binaryData = postPolicy.getBytes("utf-8");
            String encodedPolicy = BinaryUtil.toBase64String(binaryData);
            String postSignature = ossClient.calculatePostSignature(postPolicy);

            Map<String, String> result = new HashMap<>();
            result.put("accessKeyId", ossConfig.getAccessKeyId());
            result.put("policy", encodedPolicy);
            result.put("signature", postSignature);
            result.put("key", key);
            String host = ossConfig.getEndpoint().startsWith("http") ? 
                ossConfig.getEndpoint() : "https://" + ossConfig.getEndpoint();
            result.put("host", "https://" + ossConfig.getBucketName() + "." + host.replace("https://", "").replace("http://", ""));
            result.put("expire", String.valueOf(expireEndTime));

            log.info("生成OSS上传签名成功，文件key: {}", key);
            return result;

        } catch (Exception e) {
            log.error("生成OSS上传签名失败", e);
            throw new RuntimeException("生成上传签名失败: " + e.getMessage());
        }
    }

    /**
     * 获取文件扩展名
     * @param filename 文件名
     * @return 扩展名
     */
    private String getFileExtension(String filename) {
        if (filename == null || filename.isEmpty()) {
            return "";
        }
        int lastDotIndex = filename.lastIndexOf('.');
        if (lastDotIndex > 0 && lastDotIndex < filename.length() - 1) {
            return filename.substring(lastDotIndex + 1);
        }
        return "";
    }
}
